<template>
	<view class="mask flex-center">
		<view class="content botton-radius">
			<view class="content-top">
				<text class="content-top-text">{{title}}</text>
				<image class="content-top" style="top: 0;" width="100%" height="100%" src="../images/bg_top.png">
				</image>
			</view>
			<view class="content-header"></view>
			<view class="content-body">
				<view class="title">
					<text>{{subTitle}}</text>
					<!-- <text style="padding-left:20rpx;font-size: 0.5em;color: #666;">v.{{version}}</text> -->
				</view>
				<view class="body">
					<scroll-view class="box-des-scroll" scroll-y="true">
						<text class="box-des">
							{{contents}}
						</text>
					</scroll-view>
				</view>
				<view class="footer flex-center">
					<template v-if="isiOS">
						<button class="content-button" style="border: none;color: #fff;" plain @click="jumpToAppStore">
							{{downLoadBtnTextiOS}}
						</button>
					</template>
					<template v-else>
						<template v-if="!downloadSuccess">
							<view class="progress-box flex-column" v-if="downloading">
								<progress class="progress" border-radius="35" :percent="downLoadPercent"
									activeColor="#3DA7FF" show-info stroke-width="10" />
								<view style="width:100%;font-size: 28rpx;display: flex;justify-content: space-around;">
									<text>{{downLoadingText}}</text>
									<text>({{downloadedSize}}/{{packageFileSize}}M)</text>
								</view>
							</view>

							<button v-else class="content-button" style="border: none;color: #fff;" plain
								@click="downloadPackage">
								{{downLoadBtnText}}
							</button>
						</template>
						<button v-else-if="downloadSuccess && !installed" class="content-button"
							style="border: none;color: #fff;" plain :loading="installing" :disabled="installing"
							@click="installPackage">
							{{installing ? '正在安装……' : '下载完成，立即安装'}}
						</button>

						<button v-if="installed && isWGT" class="content-button" style="border: none;color: #fff;" plain
							@click="restart">
							安装完毕，点击重启
						</button>
					</template>
				</view>
			</view>

			<image v-if="!is_mandatory" class="close-img" src="../images/app_update_close.png"
				@click.stop="closeUpdate"></image>
		</view>
	</view>
</template>

<script>
const localFilePathKey = '__localFilePath__'
const platform_iOS = 'iOS'
let downloadTask = null

/**
	 * 对比版本号，如需要，请自行修改判断规则
	 * 支持比对	("3.0.0.0.0.1.0.1", "3.0.0.0.0.1")	("3.0.0.1", "3.0")	("3.1.1", "3.1.1.1") 之类的
	 * @param {Object} v1
	 * @param {Object} v2
	 * v1 > v2 return 1
	 * v1 < v2 return -1
	 * v1 == v2 return 0
	 */
function compare (v1 = '0', v2 = '0') {
  v1 = String(v1).split('.')
  v2 = String(v2).split('.')
  const minVersionLens = Math.min(v1.length, v2.length)

  let result = 0
  for (let i = 0; i < minVersionLens; i++) {
    const curV1 = Number(v1[i])
    const curV2 = Number(v2[i])

    if (curV1 > curV2) {
      result = 1
      break
    } else if (curV1 < curV2) {
      result = -1
      break
    }
  }

  if (result === 0 && (v1.length !== v2.length)) {
    const v1BiggerThenv2 = v1.length > v2.length
    const maxLensVersion = v1BiggerThenv2 ? v1 : v2
    for (let i = minVersionLens; i < maxLensVersion.length; i++) {
      const curVersion = Number(maxLensVersion[i])
      if (curVersion > 0) {
        v1BiggerThenv2 ? result = 1 : result = -1
        break
      }
    }
  }

  return result
}

export default {
  data () {
    return {
      // 从之前下载安装
      installForBeforeFilePath: '',

      // 安装
      installed: false,
      installing: false,

      // 下载
      downloadSuccess: false,
      downloading: false,

      downLoadPercent: 0,
      downloadedSize: 0,
      packageFileSize: 0,

      tempFilePath: '', // 要安装的本地包地址

      // 默认安装包信息
      title: '更新日志',
      contents: '',
      is_mandatory: false,

      // 可自定义属性
      subTitle: '发现新版本',
      downLoadBtnTextiOS: '立即跳转更新',
      downLoadBtnText: '立即下载更新',
      downLoadingText: '安装包下载中，请稍后'
    }
  },
  onLoad ({
    local_storage_key
  }) {
    if (!local_storage_key) {
      console.error('local_storage_key为空，请检查后重试')
      uni.navigateBack()
      return
    };

    const localPackageInfo = uni.getStorageSync(local_storage_key)
    if (!localPackageInfo) {
      console.error('安装包信息为空，请检查后重试')
      uni.navigateBack()
      return
    };

    const requiredKey = ['version', 'url', 'type']
    for (const key in localPackageInfo) {
      if (requiredKey.indexOf(key) !== -1 && !localPackageInfo[key]) {
        console.error(`参数 ${key} 必填，请检查后重试`)
        uni.navigateBack()
        return
      }
    }

    Object.assign(this, localPackageInfo)
    this.checkLocalStoragePackage()
  },
  onBackPress () {
    // 强制更新不允许返回
    if (this.is_mandatory) {
      return true
    }

    downloadTask && downloadTask.abort()
  },
  computed: {
    isWGT () {
      return this.type === 'wgt'
    },
    isiOS () {
      return !this.isWGT ? this.platform.includes(platform_iOS) : false
    }
  },
  methods: {
    checkLocalStoragePackage () {
      // 如果已经有下载好的包，则直接提示安装
      const localFilePathRecord = uni.getStorageSync(localFilePathKey)
      if (localFilePathRecord) {
        const {
          version,
          savedFilePath,
          installed
        } = localFilePathRecord

        // 比对版本
        if (!installed && compare(version, this.version) === 0) {
          this.downloadSuccess = true
          this.installForBeforeFilePath = savedFilePath
          this.tempFilePath = savedFilePath
        } else {
          // 如果保存的包版本小 或 已安装过，则直接删除
          this.deleteSavedFile(savedFilePath)
        }
      }
    },
    async closeUpdate () {
      if (this.downloading) {
        if (this.is_mandatory) {
          return uni.showToast({
            title: '下载中，请稍后……',
            icon: 'none',
            duration: 500
          })
        }
        uni.showModal({
          title: '是否取消下载？',
          cancelText: '否',
          confirmText: '是',
          success: res => {
            if (res.confirm) {
              downloadTask && downloadTask.abort()
              uni.navigateBack()
            }
          }
        })
        return
      }

      if (this.downloadSuccess && this.tempFilePath) {
        // 包已经下载完毕，稍后安装，将包保存在本地
        await this.saveFile(this.tempFilePath, this.version)
        uni.navigateBack()
        return
      }

      uni.navigateBack()
    },
    downloadPackage () {
      this.downloading = true

      // 下载包
      downloadTask = uni.downloadFile({
        url: this.url,
        success: res => {
          if (res.statusCode == 200) {
            this.downloadSuccess = true
            this.tempFilePath = res.tempFilePath

            // 强制更新，直接安装
            if (this.is_mandatory) {
              this.installPackage()
            }
          }
        },
        complete: () => {
          this.downloading = false

          this.downLoadPercent = 0
          this.downloadedSize = 0
          this.packageFileSize = 0

          downloadTask = null
        }
      })

      downloadTask.onProgressUpdate(res => {
        this.downLoadPercent = res.progress
        this.downloadedSize = (res.totalBytesWritten / Math.pow(1024, 2)).toFixed(2)
        this.packageFileSize = (res.totalBytesExpectedToWrite / Math.pow(1024, 2)).toFixed(2)
      })
    },
    installPackage () {
      // #ifdef APP-PLUS
      // wgt资源包安装
      if (this.isWGT) {
        this.installing = true
      }

      plus.runtime.install(this.tempFilePath, {
        force: false
      }, async res => {
        this.installing = false
        this.installed = true

        // wgt包，安装后会提示 安装成功，是否重启
        if (this.isWGT) {
          // 强制更新安装完成重启
          if (this.is_mandatory) {
            uni.showLoading({
              icon: 'none',
              title: '安装成功，正在重启……'
            })

            setTimeout(() => {
              uni.hideLoading()
              this.restart()
            }, 1000)
          }
        } else {
          const localFilePathRecord = uni.getStorageSync(localFilePathKey)
          uni.setStorageSync(localFilePathKey, {
            ...localFilePathRecord,
            installed: true
          })
        }
      }, async err => {
        // 如果是安装之前的包，安装失败后删除之前的包
        if (this.installForBeforeFilePath) {
          await this.deleteSavedFile(this.installForBeforeFilePath)
          this.installForBeforeFilePath = ''
        }

        // 安装失败需要重新下载安装包
        this.installing = false
        this.installed = false

        uni.showModal({
          title: `更新失败${this.isWGT ? '' : '，APK文件不存在'}，请重新下载`,
          content: err.message,
          showCancel: false
        })
      })

      // 非wgt包，安装跳出覆盖安装，此处直接返回上一页
      if (!this.isWGT) {
        uni.navigateBack()
      }
      // #endif
    },
    restart () {
      this.installed = false
      // #ifdef APP-PLUS
      // 更新完重启app
      plus.runtime.restart()
      // #endif
    },
    async saveFile (tempFilePath, version) {
      const [err, res] = await uni.saveFile({
        tempFilePath
      })
      if (err) {
        return
      }
      uni.setStorageSync(localFilePathKey, {
        version,
        savedFilePath: res.savedFilePath
      })
    },
    deleteSavedFile (filePath) {
      uni.removeStorageSync(localFilePathKey)
      return uni.removeSavedFile({
        filePath
      })
    },
    jumpToAppStore () {
      plus.runtime.openURL(this.url)
    }
  }
}
</script>

<style>
	page {
		background: transparent;
	}

	.flex-center {
		/* #ifndef APP-NVUE */
		display: flex;
		/* #endif */
		justify-content: center;
		align-items: center;
	}

	.mask {
		position: fixed;
		left: 0;
		top: 0;
		right: 0;
		bottom: 0;
		background-color: rgba(0, 0, 0, .65);
	}

	.botton-radius {
		border-bottom-left-radius: 30rpx;
		border-bottom-right-radius: 30rpx;
	}

	.content {
		position: relative;
		top: 0;
		width: 600rpx;
		background-color: #fff;
		box-sizing: border-box;
		padding: 0 50rpx;
		font-family: Source Han Sans CN;
	}

	.text {
		/* #ifndef APP-NVUE */
		display: block;
		/* #endif */
		line-height: 200px;
		text-align: center;
		color: #FFFFFF;
	}

	.content-top {
		position: absolute;
		top: -195rpx;
		left: 0;
		width: 600rpx;
		height: 270rpx;
	}

	.content-top-text {
		font-size: 45rpx;
		font-weight: bold;
		color: #F8F8FA;
		position: absolute;
		top: 120rpx;
		left: 50rpx;
		z-index: 1;
	}

	.content-header {
		height: 70rpx;
	}

	.title {
		font-size: 33rpx;
		font-weight: bold;
		color: #3DA7FF;
		line-height: 38px;
	}

	.footer {
		height: 150rpx;
		display: flex;
		align-items: center;
		justify-content: space-around;
	}

	.box-des-scroll {
		box-sizing: border-box;
		padding: 0 40rpx;
		height: 200rpx;
		text-align: left;
	}

	.box-des {
		font-size: 26rpx;
		color: #000000;
		line-height: 50rpx;
	}

	.progress-box {
		width: 100%;
	}

	.progress {
		width: 90%;
		height: 40rpx;
		border-radius: 35px;
	}

	.close-img {
		width: 70rpx;
		height: 70rpx;
		z-index: 1000;
		position: absolute;
		bottom: -120rpx;
		left: calc(50% - 70rpx / 2);
	}

	.content-button {
		text-align: center;
		flex: 1;
		font-size: 30rpx;
		font-weight: 400;
		color: #FFFFFF;
		border-radius: 40rpx;
		margin: 0 18rpx;

		height: 80rpx;
		line-height: 80rpx;

		background: linear-gradient(to right, #1785ff, #3DA7FF);
	}

	.flex-column {
		display: flex;
		flex-direction: column;
		align-items: center;
	}
</style>
